/**
 * 
 */
package legumes.server.dal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.UUID;

import javax.servlet.http.HttpSession;

import legumes.client.services.ToExcellException;
import legumes.server.admin.tools.GaeInitDB;
import legumes.server.usl.services.MailStallParser;
import legumes.shared.domain.AdminException;
import legumes.shared.domain.Customer;
import legumes.shared.domain.CustomerDTO;
import legumes.shared.domain.CustomerRole;
import legumes.shared.domain.HomePlaceDelivery;
import legumes.shared.domain.LatLng;
import legumes.shared.domain.LoginException;
import legumes.shared.domain.MailStallParserException;
import legumes.shared.domain.Menu;
import legumes.shared.domain.MenuItem;
import legumes.shared.domain.NewProductMarket;
import legumes.shared.domain.OnSaleProduct;
import legumes.shared.domain.Order;
import legumes.shared.domain.OrderPart;
import legumes.shared.domain.OrderPartMenuItem;
import legumes.shared.domain.OrderPartProductItem;
import legumes.shared.domain.PlaceDelivery;
import legumes.shared.domain.Product;
import legumes.shared.domain.ProductCategory;
import legumes.shared.domain.ProductVariety;
import legumes.shared.domain.Receipe;
import legumes.shared.domain.SellSession;
import legumes.shared.domain.SellSessionForCustomer;
import legumes.shared.domain.Stall;
import legumes.shared.domain.Store;
import legumes.shared.domain.StoreException;
import legumes.shared.domain.UnicityViolationException;

import org.jBCrypt.BCrypt;

import com.google.appengine.api.datastore.QueryResultIterator;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyOpts;
import com.googlecode.objectify.ObjectifyService;

public class DALLegumesServicesImpl implements IDALLegumesServices {
 
	/**
	 * For sell sessions purge
	 */
	final int MAX_SELL_SESSIONS_COUNT = 5;
	
	private static final String CUSTOMER_DTO_IN_SESSION = "customer-dto";

	private static IDALLegumesServices s_instance;
	
	public static IDALLegumesServices getInstance(){
		if(s_instance == null){
			s_instance = new DALLegumesServicesImpl();
		}
		return s_instance;
	}
	
	private DALLegumesServicesImpl(){
	}
	
	public void init(){
		registerAllDbClass();
		checkInitDb();
	}
	
	private void registerAllDbClass(){		
		ObjectifyService.register(PlaceDelivery.class);
		ObjectifyService.register(HomePlaceDelivery.class);
		
		ObjectifyService.register(Store.class);
		
		ObjectifyService.register(Customer.class);
		
		ObjectifyService.register(Order.class);
		ObjectifyService.register(OrderPart.class);
		ObjectifyService.register(OrderPartMenuItem.class);
		ObjectifyService.register(OrderPartProductItem.class);
		
		ObjectifyService.register(Menu.class);
		ObjectifyService.register(MenuItem.class);
		ObjectifyService.register(OnSaleProduct.class);
		ObjectifyService.register(ProductCategory.class);
		ObjectifyService.register(ProductVariety.class);
		ObjectifyService.register(NewProductMarket.class);
		ObjectifyService.register(Product.class);
		
		ObjectifyService.register(Stall.class);
		ObjectifyService.register(Receipe.class);
		
		ObjectifyService.register(SellSession.class);
		ObjectifyService.register(SellSessionForCustomer.class);
	}
	
	private static void checkInitDb(){
		//if root user is not present, initialize the DB
		Objectify ofy = ObjectifyService.begin();
		Customer customer = ofy.query(Customer.class).filter("email", Customer.ROOT_ID).get();
		if(customer == null){
			System.out.println("Reset the DataBase.");
			new GaeInitDB().initDB();
		}
	}

	@Override
	public Customer getCustomer(String name_) {
		Objectify ofy = ObjectifyService.begin();
		Customer car = ofy.query(Customer.class).filter("name", name_).get();
		return car;
	}
	
	@Override
	public Customer getCustomer(long uuid_) {
		Objectify ofy = ObjectifyService.begin();
		Customer car = ofy.query(Customer.class).filter("activationUuid", uuid_).get();
		return car;
	}

	@Override
	public SellSessionForCustomer getSellSessionForCustomer(CustomerDTO c_) {
		Objectify ofy = ObjectifyService.begin();
		SellSession sellSession = findLastSellSession(ofy);
		Order order = null;
		// If logged, we retrieve the order of this customer in this sell
		// session.
		if( c_ != null){
			List<Order> horders = ofy.query(Order.class).
			filter("customerId", c_.getEmail()).
			filter("date", sellSession.getCreationDate()).list();
			
			if (horders.size() > 1) {
				System.err.println("More than one order for "
						+ c_.getEmail()
						+ " and date of sellsession="
						+ sellSession.getCreationDate());
			}
			if (!horders.isEmpty()) {
				order = horders.get(0);
			} else {
				// this customer has never ordered
				// prepare an empty order
				order = new Order();
				order.addOrderPart(new OrderPart());
			}
		} else {
			// prepare an empty order
			order = new Order();
			order.addOrderPart(new OrderPart());
		}
		
		SellSessionForCustomer sellSessionForCustomer = null;
		if( sellSession != null){
			Stall stall = sellSession.getStall();

			if( order.getOrderParts().get(0).getOrderPartMenuItem().getMenu() == null){
				order.getOrderParts().get(0).getOrderPartMenuItem().setMenu(stall.getMenu());
			}

			sellSessionForCustomer = new SellSessionForCustomer(
					c_ == null ? null : c_.getEmail(), 
					sellSession.getCreationDate(), 
					stall, 
					order);
		}
		
		return sellSessionForCustomer;
	}

	@Override
	public SellSession getSellSession(long date_) {
		
		Objectify ofy = ObjectifyService.begin();
		
		SellSession hsellSession;
		
		if (date_ <= 0) {
			hsellSession = findLastSellSession(ofy);
			if (hsellSession == null) {
				hsellSession = new SellSession();
				ofy.put(hsellSession);
			}
		} else {
			hsellSession = ofy.query(SellSession.class).filter("creationDate", date_).get();
		}
	
		return hsellSession;
//		
//		
//		System.out.println("getSellSession");
//		Session session = null;
//		try {
//			session = HibernatePoint.getSessionFactory().getCurrentSession();
//			session.beginTransaction();
//
//			SellSession hsellSession;
//			if (date_ == null) {
//				hsellSession = findLastSellSession(session);
//				if (hsellSession == null) {
//					hsellSession = new SellSession();
//					session.save(hsellSession);
//				}
//			} else {
//				hsellSession = (SellSession) session.createCriteria(
//						SellSession.class).add(
//						Restrictions.eq("creationDate", date_)).uniqueResult();
//			}
//
//			Hibernate3BeanReplicator beanReplicator = new Hibernate3BeanReplicator();
//			SellSession jo = beanReplicator.copy(hsellSession,
//					SellSession.class);
//
//			return jo;
//		} finally {
//			if (session != null && session.isOpen()) {
//				session.close();
//			}
//		}

	}

	@Override
	public void setStoreOpened(boolean b_) {
		
		Objectify ofy = ObjectifyService.beginTransaction();
		
		try{
			Store store = (Store) ofy.find(Store.class, 1L);//SMA change from 0L to 1L
			store.setOpened(b_);
			ofy.put(store);
			ofy.getTxn().commit();
		}
		finally
		{
		    if (ofy.getTxn().isActive())
		        ofy.getTxn().rollback();
		}
	}

	@Override
	public boolean isStoreOpened() {
		Objectify ofy = ObjectifyService.begin();
		Store store = (Store) ofy.find(Store.class, 1L); //SMA change from 0L to 1L
		return store == null ? false : store.isOpened();
	}
	
	@Override
	public long getOpenedSellSessionId() {
		
		Objectify ofy = ObjectifyService.begin();
		
		SellSession sellSession = findLastSellSession(ofy);
		if (sellSession == null) {
			return -1;
		}
		return sellSession.getCreationDate();
		
	}

	@Override
	public List<Long> getSellSessionsDate() {
		
		Objectify ofy = ObjectifyService.begin();
		
		List<SellSession> sellSessions = 
			ofy.query(SellSession.class).order("creationDate").list();
		
		List<Long> dates = new ArrayList<Long>();
		for (SellSession ss : sellSessions) {
			dates.add( ss.getCreationDate());
		}
		
		return dates;
	}

	@Override
	public List<Product> getProducts() {
		ObjectifyOpts opts = new ObjectifyOpts().setSessionCache(true);
	    Objectify ofy = ObjectifyService.begin(opts);
		
	    
	    List<Product> hlist = ofy.query(Product.class).order("name").list();
	    return hlist; 
	}

	@Override
	public boolean hasOrderConflict(CustomerDTO c_, long sellSessionId_, Order order_) {
		if ( c_ == null) {
			return false;
		}
		
		ObjectifyOpts opts = new ObjectifyOpts().setSessionCache(true);
	    Objectify ofy = ObjectifyService.begin(opts);
		
	    SellSession sellSession = ofy.query(
				SellSession.class).filter("creationDate", sellSessionId_).get();
	    
	    
//	    SELECT * from ORDERR o 
//	    WHERE o.CUSTOMERID = :customerId
//				AND
//			  o.SELLSESSIONID = :sellSessionId
//		ORDER BY SELLSESSIONID DESC
		
	    List<Order> oldOrders = ofy.query(Order.class).
	    filter("date", sellSession.getCreationDate()).
	    filter("customerId", c_.getEmail()).list();
	    
	    boolean alreadySaved = oldOrders.contains(order_);

		return !oldOrders.isEmpty() && !alreadySaved;
	}

	@Override
	public Order save(CustomerDTO c_, long sellSessionId_, Order order_, boolean merge_)
			throws StoreException {
		if ( c_ == null) {
			return null;
		}
		
		if (!isStoreOpened()) {
			throw new StoreException(
					"Vous ne pouvez pas commander tant que le magasin est fermé.");
		}

		ObjectifyOpts opts = new ObjectifyOpts().setSessionCache(true);
	    Objectify ofy = ObjectifyService.begin(opts);
	    SellSession sellSession = ofy.query(
				SellSession.class).filter("creationDate", sellSessionId_).get();
		
		
		Order newOrder = order_;
		newOrder.setCustomerId(c_.getEmail());
		newOrder.setCustomerName(c_.getName());
		newOrder.setDate(new Date().getTime());
		try{
			Order order = ofy.find(Order.class, newOrder.getId());
			// This order is really new
			if (order == null) {
				// This is a new order
				// Search old orders in this sell session ordered by sell
				// session date descendant
				
				List<Order> oldOrders = ofy.query(Order.class).
			    filter("date", sellSession.getCreationDate()).
			    filter("customerId", c_.getEmail()).list();
	
				boolean hasOrderConflict = !oldOrders.contains(newOrder)
						&& !oldOrders.isEmpty();
	
				if (merge_ && hasOrderConflict) {
					// Add the last order with the new one
					Order lastOldOrder = oldOrders.get(0);
					lastOldOrder.plus(newOrder);
					lastOldOrder.setDate(new Date().getTime());
					
					ofy = ObjectifyService.beginTransaction();
					ofy.put(lastOldOrder);
				} else {
					// Delete old orders
					for (Order o : oldOrders) {
						sellSession.removeOrder(o);
					}
					// Add this new order
					sellSession.addOrder(newOrder);
	
					ofy = ObjectifyService.beginTransaction();
					ofy.put(sellSession);
				}
	
			} // This order already exists in database
			else {
				// Update existent order
				ofy = ObjectifyService.beginTransaction();
				ofy.put(newOrder);
			}
			ofy.getTxn().commit();
			
		}
		finally
		{
		    if (ofy.getTxn().isActive())
		        ofy.getTxn().rollback();
		}
		
		return newOrder;
		
	}

	@Override
	public Collection<Order> getOrders(long sellSessionId_) {
		ObjectifyOpts opts = new ObjectifyOpts().setSessionCache(true);
	    Objectify ofy = ObjectifyService.begin(opts);
	   
	    SellSession sellSession = ofy.query(
				SellSession.class).filter("creationDate", sellSessionId_).get();
	    return sellSession == null ? null : sellSession.getOrders();
	}
	
	@Override
	public Product addNewProductMarket(NewProductMarket newProductMarket_) {
		//Check new product name already exists
		Objectify ofy = ObjectifyService.begin();

		Product product = ofy.query(
				Product.class).filter("name", newProductMarket_.getProduct().getName()).get();
		
		if (product == null){
			ofy.put(newProductMarket_.getProduct());
			return newProductMarket_.getProduct();
		} else {
			return null;
		}
	}
	
	@Override
	public boolean validateNewProductMarket(NewProductMarket newProductMarket_) {
		//Check new product name already exists
		Objectify ofy = ObjectifyService.begin();
		
		Product product = ofy.query(
				Product.class).filter("name", newProductMarket_.getProduct().getName()).get();
		
		if (product == null){
			product = newProductMarket_.getProduct();
			if (product != null){
				ofy.put(product);
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	@Override
	public void save(Stall stall_) {
		Objectify ofy = ObjectifyService.begin();

		SellSession sellSession = ofy.query(
				SellSession.class).filter("creationDate", stall_.getSellSessionDate()).get();
		
		if (sellSession == null) {
			sellSession = new SellSession();
			sellSession.setCreationDate(stall_.getSellSessionDate());
			sellSession.setStall(stall_);
			ofy.put(sellSession);
		} else {
			sellSession.setStall(stall_);
			ofy.put(sellSession);
		}

	}

	@Override
	public SellSession newSellSession(Store store_, long fromSellSessionId_) {
		purgeSellSessions();

		Objectify ofy = ObjectifyService.begin();
		
		SellSession hsellSession = new SellSession();
		hsellSession.setCreationDate(new Date().getTime());

		if (fromSellSessionId_ > 0) {
			SellSession ss = store_.findSellSession(fromSellSessionId_);
//			SellSession ss = ofy.query(
//					SellSession.class).filter("creationDate", fromSellSessionId_).get();
//			
			hsellSession.setStall(ss.getStall().copy());
		}
		store_.addSellSession(hsellSession);
		ofy.put(store_);
		return hsellSession;

	}

	public void purgeSellSessions() {

		Objectify ofy = ObjectifyService.begin();
		List<SellSession> sellSessions = 
			ofy.query(SellSession.class).order("creationDate").list();
		
		int toPurgeCount = Math.max(0, sellSessions.size()
				- MAX_SELL_SESSIONS_COUNT);
		for (int i = 0; i < toPurgeCount; i++) {
			ofy.delete(sellSessions.get(i));
		}
//
//		Session session = null;
//		try {
//			session = HibernatePoint.getSessionFactory().getCurrentSession();
//			session.beginTransaction();
//
//			List<SellSession> sellSessions = session.createQuery(
//					"from SellSession order by creationDate asc").list();
//
//			int toPurgeCount = Math.max(0, sellSessions.size()
//					- MAX_SELL_SESSIONS_COUNT);
//			for (int i = 0; i < toPurgeCount; i++) {
//				session.delete(sellSessions.get(i));
//			}
//			session.getTransaction().commit();
//		} catch (RuntimeException t_) {
//			t_.printStackTrace();
//			if (session != null) {
//				session.getTransaction().rollback();
//			}
//			throw t_;
//		} finally {
//			if (session != null && session.isOpen()) {
//				session.close();
//			}
//		}

	}

	@Override
	public List<CustomerDTO> getCustomers() {
	    Objectify ofy = ObjectifyService.begin();
	   
	    List<Customer> hcustomers = ofy.query(Customer.class).order("email").list();
	    
	    List<CustomerDTO> hcustomersDTO = new ArrayList<CustomerDTO>();
	    for(Customer c : hcustomers){
	    	hcustomersDTO.add(new CustomerDTO(c));
	    }
	    
		return hcustomersDTO;
//	    
//	    
//		Session session = null;
//		try {
//			session = HibernatePoint.getSessionFactory().getCurrentSession();
//			session.beginTransaction();
//			List<Customer> hcustomers = session.createQuery(
//					"from Customer order by email asc").list();
//
//			Hibernate3BeanReplicator beanReplicator = new Hibernate3BeanReplicator();
//			List<Customer> jo = beanReplicator.copy(hcustomers, List.class);
//
//			return jo;
//		} finally {
//			if (session != null && session.isOpen()) {
//				session.close();
//			}
//		}

	}
	
	@Override
	public Customer updateCustomer(Customer c_) {
		Objectify ofy = ObjectifyService.beginTransaction();
		try{
			ofy.put(c_);
			ofy.getTxn().commit();
			return c_;
		} finally{
		    if (ofy.getTxn().isActive())
		        ofy.getTxn().rollback();
		}
	}
	
	@Override
	public Customer addCustomer(Customer c_) throws UnicityViolationException {
		Objectify ofy = ObjectifyService.beginTransaction();
		try{   
			c_.setActivationUuid( new UUID(0xf81d4fae7dec11d0L, 0x0).node() );
			c_.setCreationDate(new Date().getTime());
			String hashFromDB = BCrypt.hashpw(c_.getPassword(), BCrypt.gensalt() );
			c_.setPassword(hashFromDB);
			ofy.put(c_);
			ofy.getTxn().commit();
			
			return c_;
		} finally{
		    if (ofy.getTxn().isActive())
		        ofy.getTxn().rollback();
		}
	}

	@Override
	public void removeCustomer(CustomerDTO c_, String customerId_) throws AdminException, LoginException {
		if ( c_ == null) {
			throw new LoginException("Connectez-vous avant cette opération");
		}
		
		if (Customer.ROOT_ID.equals(customerId_)) {
			throw new AdminException("L'utilisateur " + Customer.ROOT_ID
					+ " ne peut pas être supprimé.");
		}

		if (c_ != null
				&& c_.getEmail().equals(customerId_)) {
			throw new AdminException(
					"Vous ne pouvez pas supprimer votre propre utilisateur !<br> Utilisez plutôt le compte "
							+ Customer.ROOT_ID + ".");
		}

		
		Objectify ofy = ObjectifyService.begin();  
		Customer c = ofy.query(Customer.class).filter("email", customerId_).get();
		if( c != null){
			ofy.delete(c);
		} else {
			throw new AdminException("Impossible de trouver l'utilisateur : " + customerId_);
		}
//		
//		
//		
//		
//		
//		Session session = null;
//		try {
//			session = HibernatePoint.getSessionFactory().getCurrentSession();
//			session.beginTransaction();
//			session.createQuery(
//					"delete from Customer c where c.email=:customerId")
//					.setString("customerId", customerId_).executeUpdate();
//			session.getTransaction().commit();
//		} catch (RuntimeException t_) {
//			t_.printStackTrace();
//			if (session != null) {
//				session.getTransaction().rollback();
//			}
//			throw t_;
//		} finally {
//			if (session != null && session.isOpen()) {
//				session.close();
//			}
//		}

	}
	

	@Override
	public void changePassword(CustomerDTO c_, String password_, String newPassword_)
			throws LoginException {
		Objectify ofy = ObjectifyService.begin();
  
		Customer c = ofy.query(Customer.class).filter("email", c_.getEmail()).get();
		if ( c == null) {
			throw new LoginException("Utilisateur inconnu : " + c_.getEmail());
		}
		
		if (!c.getPassword().equals(password_)) {
			throw new LoginException("Mot de passe actuel incorrect pour l'utilisateur : " + c_.getEmail());
		}
		
		c.setPassword(newPassword_);
		ofy.put(c);
	}

	@Override
	public void setCustomerRole(String customerId_, CustomerRole role_) {
		
		Objectify ofy = ObjectifyService.begin();

		Customer c = ofy.query(Customer.class).
		filter("email", customerId_).get();
		c.setRoles(role_.toString());
		ofy.put(c);
//		Session session = null;
//		try {
//			session = HibernatePoint.getSessionFactory().getCurrentSession();
//			session.beginTransaction();
//
//			Customer c = (Customer) session.load(Customer.class, customerId_);
//
//			c.setRoles(role_.toString());
//			session.update(c);
//
//			session.getTransaction().commit();
//		} catch (RuntimeException t_) {
//			t_.printStackTrace();
//			if (session != null) {
//				session.getTransaction().rollback();
//			}
//			throw t_;
//		} finally {
//			if (session != null && session.isOpen()) {
//				session.close();
//			}
//		}
	}

	@Override
	public void setMessageStore(String message_) {
		Objectify ofy = ObjectifyService.beginTransaction();
		try{   
			Store store = ofy.find(Store.class, 1L);//SMA change from 0L to 1L
			store.setMessage(message_);
			ofy.put(store);
			ofy.getTxn().commit();
		}finally{
		    if (ofy.getTxn().isActive())
		        ofy.getTxn().rollback();
		}
//		
//		
//		Session session = null;
//		try {
//			session = HibernatePoint.getSessionFactory().getCurrentSession();
//			session.beginTransaction();
//			Store store = (Store) session.load(Store.class, 0L);
//			store.setMessage(message_);
//			session.getTransaction().commit();
//		} catch (RuntimeException t_) {
//			t_.printStackTrace();
//			if (session != null) {
//				session.getTransaction().rollback();
//			}
//			throw t_;
//		} finally {
//			if (session != null && session.isOpen()) {
//				session.close();
//			}
//		}
	}

	@Override
	public String getMessageStore() {
		Objectify ofy = ObjectifyService.begin();
		
		Store store =ofy.find(Store.class, 1L);//SMA change from 0L to 1L
		return store == null ? null : store.getMessage();
//		
//		
//		
//		Session session = null;
//		try {
//			session = HibernatePoint.getSessionFactory().getCurrentSession();
//			session.beginTransaction();
//			Store store = (Store) session.load(Store.class, 0L);
//			return store.getMessage();
//		} catch (RuntimeException t_) {
//			t_.printStackTrace();
//			if (session != null) {
//				session.getTransaction().rollback();
//			}
//			throw t_;
//		} finally {
//			if (session != null && session.isOpen()) {
//				session.close();
//			}
//		}
	}

	@Override
	public Stall parseStallMail(String mailContent_)
			throws MailStallParserException {
		MailStallParser mailStallParser = new MailStallParser(mailContent_);
		mailStallParser.parse();
		Stall stall = mailStallParser.getStall();
		return stall;
	}
	
	
	
	
	
	
	
	
	
	
	
	
	

	@Override
	public String generateOrdersReport(long sellSessionId_)
			throws ToExcellException {
		//TODO SMA : http://www.z80.fr/2010/03/30/google-app-engine/how-to-generate-excel-files-on-google-app-engine/
		return null;
		//		Objectify ofy = ObjectifyService.begin();
//		
//		SellSession sellSession =  ofy.query(SellSession.class).
//		filter("creationDate=", sellSessionId_).get();
//		
//
//		String virtualDir = "orders-report";
//		String realDir = this.getServletContext().getRealPath(virtualDir);
//		File realDirFile = new File(realDir);
//		realDirFile.mkdirs();
//
//		// purge
//		for (File f : realDirFile.listFiles()) {
//			System.out.println("Purge excel report : " + f);
//			f.delete();
//		}
//
//		SimpleDateFormat format = new SimpleDateFormat("W E H_m_s");
//
//		String virtualPath = virtualDir + "/"
//				+ format.format(sellSession.getCreationDate()) + ".xls";
//		String realPath = this.getServletContext().getRealPath(virtualPath);
//		File reportFile = new File(realPath);
////		FileOutputStream fout = null;
////		try {
////			fout = new FileOutputStream(reportFile);
////
////			ToExcell.toExcell(sellSession.getOrders(), fout);
////
////		} catch (IOException e_) {
////			e_.printStackTrace();
////			throw new ToExcellException(e_.toString() + " : "
////					+ e_.getMessage());
////		} finally {
////			if (fout != null) {
////				try {
////					fout.close();
////				} catch (IOException e_) {
////					e_.printStackTrace();
////				}
////			}
////		}
//
//		return virtualPath;
		
		
		
		
		
		
//		
//		
//		
//		Session session = null;
//		try {
//			session = HibernatePoint.getSessionFactory().getCurrentSession();
//			session.beginTransaction();
//			SellSession sellSession = (SellSession) session
//					.createQuery(
//							"from SellSession ss where ss.creationDate = :sellSessionId")
//					.setTimestamp("sellSessionId", sellSessionId_)
//					.uniqueResult();
//
//			String virtualDir = "orders-report";
//			String realDir = this.getServletContext().getRealPath(virtualDir);
//			File realDirFile = new File(realDir);
//			realDirFile.mkdirs();
//
//			// purge
//			for (File f : realDirFile.listFiles()) {
//				System.out.println("Purge excel report : " + f);
//				f.delete();
//			}
//
//			SimpleDateFormat format = new SimpleDateFormat("W E H_m_s");
//
//			String virtualPath = virtualDir + "/"
//					+ format.format(sellSession.getCreationDate()) + ".xls";
//			String realPath = this.getServletContext().getRealPath(virtualPath);
//			File reportFile = new File(realPath);
//			FileOutputStream fout = null;
//			try {
//				fout = new FileOutputStream(reportFile);
//
//				ToExcell.toExcell(sellSession.getOrders(), fout);
//
//			} catch (IOException e_) {
//				e_.printStackTrace();
//				throw new ToExcellException(e_.toString() + " : "
//						+ e_.getMessage());
//			} finally {
//				if (fout != null) {
//					try {
//						fout.close();
//					} catch (IOException e_) {
//						e_.printStackTrace();
//					}
//				}
//			}
//
//			return virtualPath;
//		} finally {
//			if (session != null && session.isOpen()) {
//				session.close();
//			}
//		}

	}


	protected SellSession findLastSellSession(Objectify ofy_){
		SellSession ssMaxCreationDate = null;
		QueryResultIterator<SellSession> sellSessionIt = ofy_.query(SellSession.class).iterator();
		while( sellSessionIt.hasNext() ){
			SellSession ss = sellSessionIt.next();
			if( ssMaxCreationDate == null ||
					(ssMaxCreationDate != null &&
					ssMaxCreationDate.getCreationDate()< ss.getCreationDate()) ){
				ssMaxCreationDate = ss;
			}
		}
		
		return ssMaxCreationDate;
	}

	public static String toString(HttpSession session_) {
		StringBuilder sb = new StringBuilder();

		sb.append("[HttpSession ").append(" id=").append(session_.getId())
				.append(" customerDTO=").append(
						session_.getAttribute(CUSTOMER_DTO_IN_SESSION)).append(
						"\nkeepAlive=").append(
						session_.getMaxInactiveInterval())

				.append(" attributes=\n");

		Enumeration e = session_.getAttributeNames();
		int i = 0;
		while (e.hasMoreElements()) {
			sb.append("\tattribute[").append(i).append("]=").append(
					e.nextElement()).append("\n");
		}
		sb.append("]");

		return sb.toString();
	}

	@Override
	public boolean activateUserAccount(String uuid) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void saveCustomer(Customer c) {
		Objectify ofy = ObjectifyService.begin();
		ofy.put(c);
	}

	@Override
	public Customer getCustomerFromEmail(String login_) {
		Objectify ofy = ObjectifyService.begin();
		return ofy.find(Customer.class, login_);
	}

	@Override
	public Product[] getProductsStartingWith(String prefix_) {
		Objectify ofy = ObjectifyService.begin();
		QueryResultIterator<Product> products = ofy.query(Product.class).fetch().iterator();
		List<Product> productList = new ArrayList<Product>();
		String prefix = prefix_;
		if(prefix == null){
			prefix = "";
		}
		String prefixLowerCase = prefix.toLowerCase();
		while(products.hasNext()){
			Product p = products.next();
			String pName = p.getName().toLowerCase();
			if( pName.startsWith(prefixLowerCase) ||
				p.getProductVariety().getName().toLowerCase().startsWith(prefixLowerCase) ||
				p.getProductVariety().getProductCategory().getName().toLowerCase().startsWith(prefixLowerCase)
					){
				productList.add( p );
			}
		}
		Collections.sort(productList);
		
		return productList.toArray(new Product[0]);
	}

	@Override
	public ProductVariety[] getProductVarities() {
		Objectify ofy = ObjectifyService.begin();
		return ofy.query(ProductVariety.class).list().toArray(new ProductVariety[0]);
	}

	@Override
	public ProductCategory[] getProductCategories() {
		Objectify ofy = ObjectifyService.begin();
		return ofy.query(ProductCategory.class).list().toArray(new ProductCategory[0]);
	}

	@Override
	public List<Store> getUserStores(String userId_) {
		Objectify ofy = ObjectifyService.begin();
		return ofy.query(Store.class).filter("customerId", userId_).list();
	}

	@Override
	public boolean removeStore(Store store_) {
		Objectify ofy = ObjectifyService.begin();
		Store st = ofy.query(Store.class).filter("id", store_.getId()).get();
		if( st == null){
			return false;
		} else {
			ofy.delete(st);
			return true;
		}
	}

	@Override
	public boolean isStoreNameExists(String storeName_) {
		Objectify ofy = ObjectifyService.begin();
		Store st = ofy.query(Store.class).filter("storeName", storeName_).get();
		return st != null;
	}

	@Override
	public Store addStore(Store storeToAdd) {
		Objectify ofy = ObjectifyService.begin();
		ofy.put(storeToAdd);
		return storeToAdd;
	}

	@Override
	public List<Store> getStores(LatLng northEastBound_, LatLng southWestBound_) {
		Objectify ofy = ObjectifyService.begin();
		
		List<Store> stListResult = new ArrayList<Store>();
		List<Store> stList = ofy.query(Store.class).list();
		for(Store st : stList){
			if( st.checkStoreCanDeliverInBounds(northEastBound_, southWestBound_) ){
				stListResult.add(st);
			}
		}
		
		return stListResult;
	}

	@Override
	public void save(Store store_) {
		Objectify ofy = ObjectifyService.begin();
		ofy.put(store_);
	}
	
}
